import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_chat_ui/utils/audio_utils.dart';
import 'package:flutter_chat_ui/utils/dialog_utils.dart';
import 'package:flutter_chat_ui/utils/utils.dart';
import 'package:flutter_chat_ui/utils/x_toast.dart';
import 'package:flutter_chat_ui/views/chat_bottom_widgets/hold_speech_mask_view.dart';
import 'package:flutter_chat_ui/views/chat_bottom_widgets/voice_controller.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:logger/web.dart';
import 'package:speech_to_text/speech_to_text.dart' as stt;

///
/// 按住说话按钮组件
///
class HoldSpeechButtonView extends StatefulWidget {
  /// 发送语音文本内容
  final ValueChanged<String>? sendVoiceText;

  const HoldSpeechButtonView({
    super.key,
    this.sendVoiceText,
  });

  @override
  State<HoldSpeechButtonView> createState() => _HoldSpeechButtonViewState();
}

class _HoldSpeechButtonViewState extends State<HoldSpeechButtonView>
    with WidgetsBindingObserver, TickerProviderStateMixin {
  /// 语音识别实例 - 使用单例模式避免重复初始化
  /// stop()：停止语音识别，返回最后一段识别到的语音文本。
  /// cancel()：停止语音识别，丢弃所有已捕获的语音数据，不返回识别结果。
  static stt.SpeechToText? _speechInstance;
  stt.SpeechToText get _speech => _speechInstance ??= stt.SpeechToText();

  /// 语音转文本
  String _voiceToText = '';
  String _savedVoiceText = ''; // 保存已确认的语音文本

  /// 全局尺寸 - 缓存避免重复计算
  late final Size screenSize;

  /// 遮罩
  OverlayEntry? _overlayEntry;
  late final AnimationController _overlayAnimationController;

  /// 属性
  String _appName = '应用';
  bool _hasMicrophone = false; // 麦克风
  bool _hasSpeechRecognition = false; // 语音识别
  VoiceStatus _currentVoiceStatus = VoiceStatus.idle; // 缓存当前语音状态，避免频繁查询GetX

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);

    // 缓存屏幕尺寸
    screenSize = Size(
      ScreenUtil().screenWidth,
      ScreenUtil().screenHeight,
    );

    // 初始化动画控制器
    _overlayAnimationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 300),
    );

    // 异步初始化，避免阻塞UI
    _initializeAsync();
  }

  @override
  void dispose() {
    _overlayAnimationController.dispose();
    _speech.cancel();
    if (_overlayEntry?.mounted == true) {
      _overlayEntry?.remove();
    }
    _overlayEntry = null;
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: (details) => _handlerOnTapDown(),
      onTapUp: (details) => _handlerOnTapUp(),
      onLongPressStart: (details) => _handleOnLongPressStart(),
      onLongPressMoveUpdate: (details) => _handleOnLongPressMoveUpdate(details),
      onLongPressEnd: (details) => _handlerOnLongPressEnd(details),
      child: Container(
        height: 44,
        alignment: Alignment.center,
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(4),
        ),
        child: const Text(
          '按住 说话',
          style: TextStyle(
            color: Colors.black,
            fontSize: 14,
            fontWeight: FontWeight.w500,
          ),
        ),
      ),
    );
  }

  ///
  /// 异步初始化
  ///
  void _initializeAsync() async {
    try {
      // 使用缓存的权限检查结果，避免频繁调用
      _hasMicrophone = await AudioController.hasMicrophonePermission();
      _hasSpeechRecognition = await AudioController.hasSpeechRecognitionPermission();

      // 获取应用名称
      final appInfo = await Utils.getAppInfo();
      if (mounted) {
        _appName = appInfo.appName ?? '应用';
      }

      // 初始化OverlayEntry
      _createOverlayEntry();

      // 延迟初始化语音识别，避免阻塞UI
      Future.delayed(const Duration(milliseconds: 300), () => _initSpeechRecognition());
    } catch (e) {
      Logger().e('初始化失败: $e');
    } finally {}
  }

  ///
  /// 创建OverlayEntry
  ///
  void _createOverlayEntry() {
    _overlayEntry = OverlayEntry(
      builder: (context) {
        return FadeTransition(
          opacity: CurvedAnimation(
            parent: _overlayAnimationController,
            curve: Curves.easeIn,
          ),
          child: const SpeechMaskView(),
        );
      },
    );
  }

  ///
  /// 优化的语音识别初始化 - 解决卡顿问题
  ///
  Future<void> _initSpeechRecognition() async {
    if (!mounted) return;

    await _speech.initialize(
      onStatus: (status) {},
      onError: (error) {
        // 记录错误信息
        Logger().e('语音识别错误: ${error.errorMsg}');
      },
      // 优化配置参数
      debugLogging: false, // 关闭调试日志减少性能开销
    );
  }

  ///
  /// 开始录音
  ///
  void _startRecording() {
    // 使用compute在独立isolate中启动语音识别，完全避免阻塞UI线程
    Future.microtask(() async {
      try {
        await _speech.listen(
          localeId: "zh-CN",
          // 延长超时时间，例如设置为60秒
          listenFor: const Duration(seconds: 60), // 最大监听时长
          listenOptions: stt.SpeechListenOptions(
            listenMode: stt.ListenMode.deviceDefault,
          ),
          onResult: (result) {
            // 使用防抖机制处理结果，避免频繁更新UI
            _debounceTextUpdate(result.recognizedWords);
          },
        );
        Logger().d('语音识别已启动');
      } catch (e) {
        Logger().e('启动语音识别失败: $e');
      }
    });
  }

  /// 防抖文本更新 - 直接更新VoiceController
  Timer? _textUpdateTimer;
  void _debounceTextUpdate(String text) {
    _textUpdateTimer?.cancel();
    // 调整防抖时间，减少不必要的UI更新
    _textUpdateTimer = Timer(const Duration(milliseconds: 500), () {
      if (_currentVoiceStatus != VoiceStatus.cancelSend) {
        // 将新识别的文本与之前保存的文本合并
        final combinedText = _savedVoiceText.isEmpty ? text : '$_savedVoiceText$text';
        VoiceController.to.voiceToText.value = combinedText;
        _voiceToText = combinedText;
      }
    });
  }

  ///
  /// 停止录音
  ///
  Future<void> _stopRecording() async {
    await _speech.cancel();
    // 清除防抖定时器，避免延迟更新
    _textUpdateTimer?.cancel();
    // 保存当前已识别的文本
    _savedVoiceText = VoiceController.to.voiceToText.value;
  }

  ///
  /// 录音开始，显示录音mask content
  ///
  void _showSpeechMaskView() {
    // 确保Overlay存在且可用
    final overlay = Overlay.maybeOf(context);
    if (overlay == null) {
      return;
    }

    // 如果entry已经插入，先移除
    if (_overlayEntry?.mounted == true) {
      _overlayEntry?.remove();
    }

    // 同步插入遮罩，确保立即显示
    if (_overlayEntry != null && mounted) {
      overlay.insert(_overlayEntry!);
    }
    // 开始淡入动画
    _overlayAnimationController.forward();
  }

  ///
  /// 录音结束，移除录音mask content
  ///
  void _removeSpeechMaskView() {
    // 重置本地状态缓存
    _currentVoiceStatus = VoiceStatus.idle;

    // 安全移除遮罩
    if (_overlayEntry != null) {
      _overlayAnimationController.reverse().then((_) {
        _overlayEntry!.remove(); // 动画结束后移除OverlayEntry
        _voiceToText = '';
        _savedVoiceText = ''; // 清理保存的文本
      });
    }
  }

  ///
  /// 执行点击触发【onTapDown】
  ///
  void _handlerOnTapDown() {
    // 开启震动
    HapticFeedback.heavyImpact();

    // 权限判断
    if (!_hasMicrophone) {
      DialogUtils.showAppSettingsDialog(
        context,
        title: '麦克风服务已关闭',
        message: '您需要打开麦克风权限，才可以进行语音录制。请到设置->隐私->麦克风服务中开启$_appName的麦克风',
      );
      return;
    }
    if (!_hasSpeechRecognition) {
      DialogUtils.showAppSettingsDialog(
        context,
        title: '语音识别服务已关闭',
        message: '您需要打开语音识别权限，才可以进行语音识别转中文。请到设置->隐私->语音识别服务中开启$_appName的语音识别',
      );
      return;
    }

    // 显示遮罩
    _showSpeechMaskView();
  }

  ///
  /// 执行点击触发【onTapUp】
  ///
  void _handlerOnTapUp() async {
    // 隐藏语音遮罩,并做出提示
    await Future.delayed(const Duration(milliseconds: 500));
    _removeSpeechMaskView();
    await Future.delayed(const Duration(milliseconds: 250));
    XToast.showInfo(
      '说话时间太短',
      duration: const Duration(milliseconds: 1200),
    );
  }

  ///
  /// 执行长按触发【onLongPressStart】
  ///
  void _handleOnLongPressStart() {
    if (_hasMicrophone && _hasSpeechRecognition) {
      // 初始化保存的文本
      _savedVoiceText = '';
      // 立即更新本地状态缓存
      _currentVoiceStatus = VoiceStatus.recording;
      // 启动语音识别
      _startRecording();
    }
  }

  ///
  /// 执行长按触发【onLongPressEnd】
  ///
  void _handlerOnLongPressEnd(LongPressEndDetails details) {
    // 结束录音识别
    _stopRecording();

    // 滑动是否超过底部录音范围
    final offset = details.globalPosition;
    final isCanceling = (screenSize.height - offset.dy.abs()) > Utils.voiceBgOvalHeight;

    if (!isCanceling) {
      // 在语音录制内，发送语音信息
    }

    // 移除语音遮罩
    _removeSpeechMaskView();
  }

  ///
  /// 处理长按触发【onLongPressMoveUpdate】
  ///
  void _handleOnLongPressMoveUpdate(LongPressMoveUpdateDetails details) {
    final offset = details.globalPosition;
    final isCanceling = (screenSize.height - offset.dy.abs()) > Utils.voiceBgOvalHeight; // 滑动超过底部录音范围

    if (isCanceling) {
      // 只有当前不是取消状态时才切换
      if (_currentVoiceStatus != VoiceStatus.cancelSend) {
        _currentVoiceStatus = VoiceStatus.cancelSend;
        // 更新VoiceController状态
        VoiceController.to.updateStatus(VoiceStatus.cancelSend);
        // 停止录音识别，丢弃当前识别内容
        _stopRecording();
      }
    } else {
      // 只有当前不是录制状态时才切换
      if (_currentVoiceStatus != VoiceStatus.recording) {
        _currentVoiceStatus = VoiceStatus.recording;
        // 更新VoiceController状态
        VoiceController.to.updateStatus(VoiceStatus.recording);
        // 重新开始录音识别
        _startRecording();
      }
    }
  }
}
